/*
 * Socket.cpp
 *
 *  Created on: 2012-10-15
 *      Author: tony
 */

#include "Socket.h"
#include "AutoLock.h"
#include <iostream>
/* Constants */
const WORD WSA_VERSION=MAKEWORD(2,2);

/* Static Initializers */
bool Socket::sm_is_wsa_started = false;
CriticalSection Socket::sm_criticalsection;
WSAData Socket::sm_wsa_data;

Socket::Socket()
: m_listen_socket(INVALID_SOCKET)
{
	AutoLock< CriticalSection > Lock(sm_criticalsection);
	if( sm_is_wsa_started == false )
	{
		// WSAStartup to be called once per process
		int result = WSAStartup(WSA_VERSION, &sm_wsa_data);
		if( result == 0 )
		{
			sm_is_wsa_started = true;
		}
		else
		{
			sm_is_wsa_started = false;
		}
	}
}

Socket::~Socket()
{
	AutoLock< CriticalSection > Lock(sm_criticalsection);
	if( sm_is_wsa_started == true )
	{
		WSACleanup();
	}
}

void Socket::Run()
{

}

SocketError Socket::StartServer(const char* port)
{
	SocketError result(0);

	struct addrinfo* presult=0;
	struct addrinfo hints;

	ZeroMemory( &hints, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;

	// a successful getaddrinfo must always have a freeaddrinfo
	result = getaddrinfo(0, port, &hints, &presult);
	if( result.GetError() == 0 )
	{
		// Create the listening socket
		m_listen_socket = socket(presult->ai_family, presult->ai_socktype, presult->ai_protocol);
		if( m_listen_socket != INVALID_SOCKET )
		{
			// Bind the listen socket
			if( bind(m_listen_socket, presult->ai_addr, presult->ai_addrlen) != SOCKET_ERROR )
			{
				// Start listening
				if( listen( m_listen_socket, SOMAXCONN) != SOCKET_ERROR )
				{
					// Start socket thread
				}
				else
				{
					// error listening
					result = WSAGetLastError();
					closesocket(m_listen_socket);
				}
			}
			else
			{
				// error binding
				result = WSAGetLastError();
				closesocket(m_listen_socket);
			}
		}
		else
		{
			// error creating socket
			result = WSAGetLastError();
		}

		// cleanup the result from getaddrinfo
		freeaddrinfo(presult);
	}

	return result;
}
